home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / timidsrc.zip / motif_c.c < prev    next >
C/C++ Source or Header  |  1996-05-20  |  10KB  |  438 lines

  1. /* 
  2.  
  3.     TiMidity -- Experimental MIDI to WAVE converter
  4.     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     motif_ctl.c: written by Vincent Pagel (pagel@loria.fr) 10/4/95
  21.    
  22.     A motif interface for TIMIDITY : to prevent X redrawings from 
  23.     interfering with the audio computation, I don't use the XtAppAddWorkProc
  24.  
  25.     I create a pipe between the timidity process and a Motif interface
  26.     process forked from the 1st one
  27.  
  28.     */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <stdarg.h>
  34.  
  35. #include "config.h"
  36. #include "common.h"
  37. #include "instrum.h"
  38. #include "playmidi.h"
  39. #include "output.h"
  40. #include "controls.h"
  41. #include "motif.h"
  42.  
  43. static void ctl_refresh(void);
  44. static void ctl_total_time(int tt);
  45. static void ctl_master_volume(int mv);
  46. static void ctl_file_name(char *name);
  47. static void ctl_current_time(int ct);
  48. static void ctl_note(int v);
  49. static void ctl_program(int ch, int val);
  50. static void ctl_volume(int channel, int val);
  51. static void ctl_expression(int channel, int val);
  52. static void ctl_panning(int channel, int val);
  53. static void ctl_sustain(int channel, int val);
  54. static void ctl_pitch_bend(int channel, int val);
  55. static void ctl_reset(void);
  56. static int ctl_open(int using_stdin, int using_stdout);
  57. static void ctl_close(void);
  58. static int ctl_read(int32 *valp);
  59. static int cmsg(int type, int verbosity_level, char *fmt, ...);
  60. static void ctl_pass_playing_list(int number_of_files, char *list_of_files[]);
  61.  
  62. /**********************************************/
  63. /* export the interface functions */
  64.  
  65. #define ctl motif_control_mode
  66.  
  67. ControlMode ctl= 
  68. {
  69.   "motif interface", 'm',
  70.   1,0,0,
  71.   ctl_open, ctl_pass_playing_list, ctl_close, ctl_read, cmsg,
  72.   ctl_refresh, ctl_reset, ctl_file_name, ctl_total_time, ctl_current_time, 
  73.   ctl_note, 
  74.   ctl_master_volume, ctl_program, ctl_volume, 
  75.   ctl_expression, ctl_panning, ctl_sustain, ctl_pitch_bend
  76. };
  77.  
  78.  
  79. /***********************************************************************/
  80. /* Put controls on the pipe                                            */
  81. /***********************************************************************/
  82. static int cmsg(int type, int verbosity_level, char *fmt, ...)
  83. {
  84.     char local[255];
  85.  
  86.     va_list ap;
  87.     if ((type==CMSG_TEXT || type==CMSG_INFO || type==CMSG_WARNING) &&
  88.     ctl.verbosity<verbosity_level)
  89.     return 0;
  90.  
  91.     va_start(ap, fmt);
  92.     if (!ctl.opened)
  93.     {
  94.         vfprintf(stderr, fmt, ap);
  95.         fprintf(stderr, "\n");
  96.     }
  97.     else if (ctl.trace_playing)
  98.     {
  99.         vsprintf(local, fmt, ap);
  100.         pipe_int_write(CMSG_MESSAGE);
  101.         pipe_int_write(type);
  102.         pipe_string_write(local);
  103.     }
  104.     va_end(ap);
  105.     return 0;
  106. }
  107.  
  108.  
  109. static void _ctl_refresh(void)
  110. {
  111.     /* pipe_int_write(REFRESH_MESSAGE); */
  112. }
  113.  
  114. static void ctl_refresh(void)
  115. {
  116.   if (ctl.trace_playing)
  117.     _ctl_refresh();
  118. }
  119.  
  120. static void ctl_total_time(int tt)
  121. {
  122.   int centisecs=tt/(play_mode->rate/100);
  123.  
  124.   pipe_int_write(TOTALTIME_MESSAGE);
  125.   pipe_int_write(centisecs);
  126. }
  127.  
  128. static void ctl_master_volume(int mv)
  129. {
  130.     pipe_int_write(MASTERVOL_MESSAGE);
  131.     pipe_int_write(mv);
  132. }
  133.  
  134. static void ctl_file_name(char *name)
  135. {
  136.     pipe_int_write(FILENAME_MESSAGE);
  137.     pipe_string_write(name);
  138. }
  139.  
  140. static void ctl_current_time(int ct)
  141. {
  142.     int i,v;
  143.     int centisecs=ct/(play_mode->rate/100);
  144.  
  145.     if (!ctl.trace_playing) 
  146.     return;
  147.            
  148.     v=0;
  149.     i=voices;
  150.     while (i--)
  151.     if (voice[i].status!=VOICE_FREE) v++;
  152.     
  153.     pipe_int_write(CURTIME_MESSAGE);
  154.     pipe_int_write(centisecs);
  155.     pipe_int_write(v);
  156. }
  157.  
  158. static void ctl_note(int v)
  159. {
  160.     /*   int xl;
  161.     if (!ctl.trace_playing) 
  162.     return;
  163.     xl=voice[v].note%(COLS-24);
  164.     wmove(dftwin, 8+voice[v].channel,xl+3);
  165.     switch(voice[v].status)
  166.     {
  167.     case VOICE_DIE:
  168.         waddch(dftwin, ',');
  169.         break;
  170.     case VOICE_FREE: 
  171.         waddch(dftwin, '.');
  172.         break;
  173.     case VOICE_ON:
  174.         wattron(dftwin, A_BOLD);
  175.         waddch(dftwin, '0'+(10*voice[v].velocity)/128); 
  176.         wattroff(dftwin, A_BOLD);
  177.         break;
  178.     case VOICE_OFF:
  179.     case VOICE_SUSTAINED:
  180.         waddch(dftwin, '0'+(10*voice[v].velocity)/128);
  181.         break;
  182.     }
  183.     */
  184. }
  185.  
  186. static void ctl_program(int ch, int val)
  187. {
  188. /*  if (!ctl.trace_playing) 
  189.     return;
  190.   wmove(dftwin, 8+ch, COLS-20);
  191.   if (ISDRUMCHANNEL(ch))
  192.     {
  193.       wattron(dftwin, A_BOLD);
  194.       wprintw(dftwin, "%03d", val);
  195.       wattroff(dftwin, A_BOLD);
  196.     }
  197.   else
  198.     wprintw(dftwin, "%03d", val);
  199.     */
  200. }
  201.  
  202. static void ctl_volume(int channel, int val)
  203. {
  204.     /*
  205.       if (!ctl.trace_playing) 
  206.     return;
  207.   wmove(dftwin, 8+channel, COLS-16);
  208.   wprintw(dftwin, "%3d", (val*100)/127);
  209.   */
  210. }
  211.  
  212. static void ctl_expression(int channel, int val)
  213. {
  214. /*  if (!ctl.trace_playing) 
  215.     return;
  216.   wmove(dftwin, 8+channel, COLS-12);
  217.   wprintw(dftwin, "%3d", (val*100)/127);
  218.   */
  219. }
  220.  
  221. static void ctl_panning(int channel, int val)
  222. {
  223. /*  if (!ctl.trace_playing) 
  224.     return;
  225.   
  226.   if (val==NO_PANNING)
  227.     waddstr(dftwin, "   ");
  228.   else if (val<5)
  229.     waddstr(dftwin, " L ");
  230.   else if (val>123)
  231.     waddstr(dftwin, " R ");
  232.   else if (val>60 && val<68)
  233.     waddstr(dftwin, " C ");
  234.     */
  235. }
  236.  
  237. static void ctl_sustain(int channel, int val)
  238. {
  239. /*
  240.   if (!ctl.trace_playing) 
  241.     return;
  242.  
  243.   if (val) waddch(dftwin, 'S');
  244.   else waddch(dftwin, ' ');
  245.   */
  246. }
  247.  
  248. static void ctl_pitch_bend(int channel, int val)
  249. {
  250. /*  if (!ctl.trace_playing) 
  251.     return;
  252.  
  253.   if (val>0x2000) waddch(dftwin, '+');
  254.   else if (val<0x2000) waddch(dftwin, '-');
  255.   else waddch(dftwin, ' ');
  256.   */
  257. }
  258.  
  259. static void ctl_reset(void)
  260. {
  261. /*  int i,j;
  262.   if (!ctl.trace_playing) 
  263.     return;
  264.   for (i=0; i<16; i++)
  265.     {
  266.     ctl_program(i, channel[i].program);
  267.     ctl_volume(i, channel[i].volume);
  268.     ctl_expression(i, channel[i].expression);
  269.     ctl_panning(i, channel[i].panning);
  270.     ctl_sustain(i, channel[i].sustain);
  271.     ctl_pitch_bend(i, channel[i].pitchbend);
  272.     }
  273.   _ctl_refresh();
  274.   */
  275. }
  276.  
  277. /***********************************************************************/
  278. /* OPEN THE CONNECTION                                                */
  279. /***********************************************************************/
  280. static int ctl_open(int using_stdin, int using_stdout)
  281. {
  282.   ctl.opened=1;
  283.   ctl.trace_playing=1;    /* Default mode with Motif interface */
  284.   
  285.   /* The child process won't come back from this call  */
  286.   pipe_open();
  287.  
  288.   return 0;
  289. }
  290.  
  291. /* Tells the window to disapear */
  292. static void ctl_close(void)
  293. {
  294.   if (ctl.opened)
  295.     {
  296.     pipe_int_write(CLOSE_MESSAGE);
  297.     ctl.opened=0;
  298.     }
  299. }
  300.  
  301.  
  302. /* 
  303.  * Read information coming from the window in a BLOCKING way
  304.  */
  305. static int ctl_blocking_read(int32 *valp)
  306. {
  307.   int command;
  308.   int new_volume;
  309.   int new_centiseconds;
  310.  
  311.   pipe_int_read(&command);
  312.   
  313.   while (1)    /* Loop after pause sleeping to treat other buttons! */
  314.       {
  315.  
  316.       switch(command)
  317.           {
  318.           case MOTIF_CHANGE_VOLUME:
  319.           pipe_int_read(&new_volume);
  320.           *valp= new_volume - amplification ;
  321.           return RC_CHANGE_VOLUME;
  322.           
  323.           case MOTIF_CHANGE_LOCATOR:
  324.           pipe_int_read(&new_centiseconds);
  325.           *valp= new_centiseconds*(play_mode->rate / 100) ;
  326.           return RC_JUMP;
  327.           
  328.           case MOTIF_QUIT:
  329.           return RC_QUIT;
  330.         
  331.           case MOTIF_PLAY_FILE:
  332.           return RC_LOAD_FILE;          
  333.           
  334.           case MOTIF_NEXT:
  335.           return RC_NEXT;
  336.           
  337.           case MOTIF_PREV:
  338.           return RC_REALLY_PREVIOUS;
  339.           
  340.           case MOTIF_RESTART:
  341.           return RC_RESTART;
  342.           
  343.           case MOTIF_FWD:
  344.           *valp=play_mode->rate;
  345.           return RC_FORWARD;
  346.           
  347.           case MOTIF_RWD:
  348.           *valp=play_mode->rate;
  349.           return RC_BACK;
  350.           }
  351.       
  352.       
  353.       if (command==MOTIF_PAUSE)
  354.           {
  355.           pipe_int_read(&command); /* Blocking reading => Sleep ! */
  356.           if (command==MOTIF_PAUSE)
  357.               return RC_NONE; /* Resume where we stopped */
  358.           }
  359.       else 
  360.           {
  361.           fprintf(stderr,"UNKNOWN RC_MESSAGE %i\n",command);
  362.           return RC_NONE;
  363.           }
  364.       }
  365.  
  366. }
  367.  
  368. /* 
  369.  * Read information coming from the window in a non blocking way
  370.  */
  371. static int ctl_read(int32 *valp)
  372. {
  373.   int num;
  374.  
  375.   /* We don't wan't to lock on reading  */
  376.   num=pipe_read_ready(); 
  377.  
  378.   if (num==0)
  379.       return RC_NONE;
  380.   
  381.   return(ctl_blocking_read(valp));
  382. }
  383.  
  384. static void ctl_pass_playing_list(int number_of_files, char *list_of_files[])
  385. {
  386.     int i=0;
  387.     char file_to_play[1000];
  388.     int command;
  389.     int32 val;
  390.  
  391.     /* Pass the list to the interface */
  392.     pipe_int_write(FILE_LIST_MESSAGE);
  393.     pipe_int_write(number_of_files);
  394.     for (i=0;i<number_of_files;i++)
  395.     pipe_string_write(list_of_files[i]);
  396.     
  397.     /* Ask the interface for a filename to play -> begin to play automatically */
  398.     pipe_int_write(NEXT_FILE_MESSAGE);
  399.     
  400.     command = ctl_blocking_read(&val);
  401.  
  402.     /* Main Loop */
  403.     for (;;)
  404.     { 
  405.         if (command==RC_LOAD_FILE)
  406.         {
  407.             /* Read a LoadFile command */
  408.             pipe_string_read(file_to_play);
  409.             command=play_midi_file(file_to_play);
  410.         }
  411.         else
  412.         {
  413.             if (command==RC_QUIT)
  414.             return;
  415.             if (command==RC_ERROR)
  416.             command=RC_TUNE_END; /* Launch next file */
  417.         
  418.  
  419.             switch(command)
  420.             {
  421.             case RC_NEXT:
  422.                 pipe_int_write(NEXT_FILE_MESSAGE);
  423.                 break;
  424.             case RC_REALLY_PREVIOUS:
  425.                 pipe_int_write(PREV_FILE_MESSAGE);
  426.                 break;
  427.             case RC_TUNE_END:
  428.                 pipe_int_write(TUNE_END_MESSAGE);
  429.                 break;
  430.             default:
  431.                 printf("PANIC !!! OTHER COMMAND ERROR ?!?! %i\n",command);
  432.             }
  433.             
  434.             command = ctl_blocking_read(&val);
  435.         }
  436.     }
  437. }
  438.